\documentclass[9pt]{extarticle}

\usepackage[table]{xcolor}
\usepackage{amsmath}
\usepackage{booktabs}
\usepackage{bytefield}
\usepackage{caption}
\usepackage{endnotes}
\usepackage{fancyvrb}
\usepackage{float}
\usepackage{longtable}
\usepackage{minibox}
\usepackage{register}
\usepackage{standalone}
\usepackage{swiftnav}
\usepackage{tabularx}
\usepackage{tocloft}
\usepackage{setspace}
\usepackage{pbox}
\usepackage{soul}
\usepackage{hyperref}
\usepackage{ltxtable}

\hypersetup{bookmarks,bookmarksopen,bookmarksdepth=4}

\setlength{\regWidth}{0.4\textwidth}

\floatstyle{plain}
\newfloat{field}{h}{fld}
\floatname{field}{Field}

\numberwithin{table}{subsection}
\numberwithin{field}{subsection}

\renewcommand{\version}{(((version)))}
\renewcommand{\thesubsubsection}{\hspace{-0.45cm}}

\newcommand{\specialcell}[2][c]{%
  \begin{tabular}[#1]{@{}c@{}}#2\end{tabular}}

\renewcommand{\regLabelFamily}{}

\cftsetindents{section}{0.5in}{0.5in}
\cftsetindents{subsection}{0.5in}{0.5in}
%%\setlength\cftparskip{-1.2pt}
\setlength{\cftbeforetoctitleskip}{-1em}
\setlength\cftbeforesecskip{1.3pt}
\setlength\cftaftertoctitleskip{2pt}
\renewcommand{\cftsecafterpnum}{\hspace*{7.5em}}
\renewcommand{\cftsubsecafterpnum}{\hspace*{7.5em}}
\renewcommand\tableofcontents{\@starttoc{toc}}

\newcolumntype{Z}{>{\hsize=.15\hsize}X}
\newcolumntype{a}{>{\hsize=.2\hsize}X}
\newcolumntype{b}{>{\hsize=.22\hsize}X}
\newcolumntype{c}{>{\hsize=.3\hsize}X}
\newcolumntype{d}{>{\hsize=.7\hsize}X}
\newcolumntype{e}{>{\hsize=.13\hsize}X}
\newcolumntype{f}{>{\hsize=.16\hsize}X}
\newcolumntype{g}{>{\hsize=.77\hsize}X}
\newcolumntype{h}{>{\hsize=.6\hsize}X}
\newcolumntype{N}{>{\hsize=.77\hsize}X}

% Shell out to git to get the most recent tag and pass it to the LateX
% job name. Hopefully this doesn't screw with things.
\immediate\write18{git describe --abbrev=0 --tags | cut -c 2-5 > \jobname.info }

\title{Swift Navigation Binary Protocol}
\author{Swift Navigation}
\mysubtitle{Protocol Specification \version}
\date{\today}

\begin{document}
\maketitle
\begin{normalsize}
\setcounter{tocdepth}{2}
\begin{centering}
\tableofcontents
\end{centering}
\end{normalsize}

\thispagestyle{firstpage}
\bigskip
\bigskip
\begin{large}
\section{Overview}
\label{sec:Overview}
The Swift Navigation Binary Protocol (SBP) is a fast, simple, and
minimal binary protocol for communicating with Swift devices. It is
the native binary protocol used by the Piksi GPS receiver to transmit
solutions, observations, status, and debugging messages, as well as
receive messages from the host operating system, such as differential
corrections and the almanac. As such, it is an important interface
with your Piksi receiver and the primary integration method with other
systems.

This document provides a specification of SBP framing and the payload
structures of the messages currently used with Swift devices. SBP
client libraries in a variety of programming languages are available
at~\url{https://github.com/swift-nav/libsbp} and support information
for sbp is available at~\url{https://support.swiftnav.com/customer/en/portal/articles/2492810-swift-binary-protocol}.

\end{large}

\newpage
\section{Message Framing Structure}
\label{sec:Message}

\begin{large}
SBP consists of two pieces:
\begin{itemize}
  \item an over-the-wire message framing format
  \item structured payload definitions
\end{itemize}
As of Version~\version, the frame consists of a 6-byte binary
header section, a variable-sized payload field, and a 16-bit CRC
value. All multibyte values are ordered in \textbf{little-endian}
format. SBP uses the CCITT CRC16 (XMODEM implementation) for error
detection\footnote{CCITT 16-bit CRC Implementation uses parameters
  used by XMODEM, i.e. the polynomial: $x^{16} + x^{12} + x^5 +
  1$. For more details, please see the implementation
  at~\url{https://github.com/swift-nav/libsbp/blob/master/c/src/edc.c\#L59}. See
  also \emph{A Painless Guide to CRC Error Detection Algorithms}
  at~\url{http://www.ross.net/crc/download/crc_v3.txt}}.

\end{large}

\begin{table}[h]
  \centering
  \begin{tabularx}{\textwidth}{aaaX}
    \toprule
    Offset (bytes) & Size (bytes) & Name & Description \\
    \midrule
    $\mathtt{0}$ & $\mathtt{1}$ & {Preamble} & Denotes the start of frame transmission. Always 0x55. \\
    $\mathtt{1}$ & $\mathtt{2}$ & {Message Type} & Identifies the payload contents. \\
    $\mathtt{3}$ & $\mathtt{2}$ & {Sender} & A unique identifier of the sender.\footnotemark \\
    $\mathtt{5}$ & $\mathtt{1}$ & {Length} & Length (bytes) of the {Payload} field. \\
    $\mathtt{6}$ & $\mathtt{N}$ & {Payload} & Binary message contents. \\
    $\mathtt{N+6}$ & $\mathtt{2}$ & {CRC} & \hangindent=0.5em{Cyclic Redundancy Check of the frame's binary data from the Message Type up to the end of Payload (does not include the Preamble).} \\
    \midrule
    & $\mathtt{N+8}$ & &Total Frame Length \\
    \bottomrule
  \end{tabularx}
  \caption{Swift Binary Protocol message structure. $\mathtt{N}$ denotes a variable-length size.}
  \label{tab:message}
\end{table}
\footnotetext{By default, clients of `libsbp` use a sender id value of `0x42` which represents device controllers such as the Piksi Console. On the Piksi, the sender ID is set to the 2 least significant bytes of the device serial number. A stream of SBP messages may also include sender IDs for forwarded messages from other systems. For instance, when using Starling as a hosted software product, Sender 0x1000 (4096) indicates a message originated from the GNSS subsystem, while sender 0x315 (789) indicates a message originated from the sensor fusion subsystem. Sender 0 always indicates the message has been forwarded and contains some form of differential corrections.}

\section{NMEA-0183}
\label{sec:NMEA}

\begin{large}

Swift devices, such as the Piksi, also have limited support for the standard
NMEA-0183 protocol.

Note that NMEA-0183 doesn't define standardized message
string equivalents for many important SBP messages such as observations,
baselines and ephemerides. For this reason it is strongly recommended to use
SBP for new development. NMEA-0183 output is provided primarily to support
legacy devices.

\end{large}

\newpage

\section{Basic Formats and Payload Structure}
\label{sec:Payload}
\begin{large}
The binary payload of an SBP message decodes into structured data
based on the message type defined in the header. SBP uses several
primitive numerical and collection types for defining payload
contents.
\end{large}
\begin{table}[h]
  \centering
  \begin{tabularx}{\textwidth}{aaX}
    \toprule
    Name & Size (bytes) & Description \\
    \midrule
    ((*- for t in prims *))
    (((t.identifier))) & (((t.identifier | getsize))) & \hangindent=0.5em{(((t.desc)))} \\
    ((*- endfor *))
    \bottomrule
  \end{tabularx}
  \caption{SBP primitive types}
  \label{tab:types}
\end{table}
\hspace{-5em}
\subsubsection*{Example Message}
\begin{large}
 \par As an example, consider this framed series of bytes read from a
 serial port:
\begin{verbatim}
55 0b 02 cc 04 14 70 3d d0 18 cf ef ff ff ef e8 ff ff f0 18 00 00 00 00 05 00 15 dc
\end{verbatim}
This byte array decodes into a \texttt{MSG\_BASELINE\_ECEF} (see
pg.~\pageref{sec:MSG_BASELINE_ECEF}), which reports the baseline position
solution of the rover receiver relative to the base station receiver
in Earth Centered Earth Fixed (ECEF) coordinates. The segments of this
byte array and its contents break down as follows:
\end{large}
\begin{table}[h]
  \centering
  \begin{tabular}{llrl}
    \toprule
    Field Name & Type & Value & Bytestring Segment\\
    \midrule
    {Preamble} & u8 & 0x55 & \verb!55! \\
    {Message Type}& u16 & \texttt{MSG\_BASELINE\_ECEF} & \verb!0b 02! \\
    {Sender}& u16 & 1228 & \verb!cc 04! \\
    {Length}& u8 & 20 &  \verb!14! \\
    {Payload}& & --- & \verb!70 3d d0 18 cf ef ff ff ef e8 ff ff! \\
    & & & \verb!f0 18 00 00 00 00 05 00! \\
    \quad~\texttt{MSG\_BASELINE\_ECEF} & & & \\
    \quad~.tow & u32 & $416300400~\textrm{msec}$  & \verb!70 3d d0 18! \\
    \quad~.x & s32 & $-4145~\textrm{mm}$  & \verb!cf ef ff ff! \\
    \quad~.y & s32 & $-5905~\textrm{mm}$  & \verb!ef e8 ff ff! \\
    \quad~.z & s32 & $6384~\textrm{mm}$  & \verb!f0 18 00 00! \\
    \quad~.accuracy & u16 & 0 & \verb!00 00! \\
    \quad~.nsats & u8 & 5 & \verb!05! \\
    \quad~.flags & u8 & 0 & \verb!00! \\
    {CRC} & u16 & 0x9443 & \verb!15 dc! \\
    \bottomrule
  \end{tabular}
  \caption{SBP breakdown for \texttt{MSG\_BASELINE\_ECEF}}
  \label{tab:example_breakdown}
\end{table}

\newpage

\section{GNSS Signals}
\label{sec:signals}
\begin{large}
Code, Constellation, and Band. Signal descriptions are provided in both RINEX and ICD Conventions.
\end{large}\\

\begin{center}
  \begin{longtable}{{llllllp{6.5cm}}}
    \toprule
    Value & Rinex Desc. & ICD Desc. & Value & Rinex Desc. & ICD Desc. \\
    \midrule
    {0} & {GPS L1CA} & {GPS L1 C/A} & {30} & {GLO L2P} & {GLONASS L2SF} \\
    {1} & {GPS L2CM} & {GPS L2C M} & {31} & {QZS L1CA} & {QZS L1 C/A} \\
    {2} & {SBAS L1CA} & {SBAS L1 C/A} & {32} & {QZS L1CI} & {QZS L1C D} \\
    {3} & {GLO L1OF} & {GLONASS L10F} & {33} & {QZS L1CQ} & {QZS L1C P} \\
    {4} & {GLO L20F} & {GLONASS L20F} & {34} & {QZS L1CX} & {QZS L1C D+P} \\
    {5} & {GPS L1P} & {GPS L1 P(Y)} & {35} & {QZS L2CM} & {QZS L2C M} \\
    {6} & {GPS L2P} & {GPS L2 P(Y)} & {36} & {QZS L2CL} & {QZS L2C L} \\
    {7} & {GPS L2CL} & {GPS L2C L} & {37} & {QZS L2CX} & {QZS L2C ML} \\
    {8} & {GPS L2CX} & {GPS L2C M+L} & {38} & {QZS L5I} & {QZS L5 I} \\
    {9} & {GPS L5I} & {GPS L5 I} & {39} & {QZS L5Q} & {QZS L5 Q} \\
    {10} & {GPS L5Q} & {GPS L5 Q} & {40} & {QZS L5X} & {QZS L5 I+Q} \\
    {11} & {GPS L5X} & {GPS L5 I+Q} & {41} & {SBAS L5I} & {SBAS L5 I} \\
    {12} & {BDS2 B1} & {BDS B1I} & {42} & {SBAS L5Q} & {SBAS L5 Q} \\
    {13} & {BDS2 B2} & {BDS B2I} & {43} & {SBAS L5X} & {SBAS L5 I+Q} \\
    {14} & {GAL E1B} & {GAL E1 B} & {44} & {BDS3 B1CI} & {BDS B1C D} \\
    {15} & {GAL E1C} & {GAL E1 C} & {45} & {BDS3 B1CQ} & {BDS B1C P} \\
    {16} & {GAL E1X} & {GAL E1 B+C} & {46} & {BDS3 B1CX} & {BDS B1C D+P} \\
    {17} & {GAL E6B} & {GAL E6 B} & {47} & {BDS3 B5I} & {BDS B2a D} \\
    {18} & {GAL E6C} & {GAL E6 C} & {48} & {BDS3 B5Q} & {BDS B2a P} \\
    {19} & {GAL E6X} & {GAL E6 B+C} & {49} & {BDS3 B5X} & {BDS B2a D+P} \\
    {20} & {GAL E7I} & {GAL E5b I} & {50} & {BDS3 B7I} & {BDS B2b D} \\
    {21} & {GAL E7Q} & {GAL E5b Q} & {51} & {BDS3 B7Q} & {BDS B2b P} \\
    {22} & {GAL E7X} & {GAL E5b I+Q} & {52} & {BDS3 B7X} & {BDS B2b D+P} \\
    {23} & {GAL E8I} & {GAL E5a+b I} & {53} & {BDS3 B3I} & {BDS B3I} \\
    {24} & {GAL E8I} & {GAL E5a+b Q} & {54} & {BDS3 B3Q} & {BDS B3Q} \\
    {25} & {GAL E8X} & {GAL E5a+b I+Q} & {55} & {BDS3 B3X} & {BDS B3 I+Q} \\
    {26} & {GAL E5I} & {GAL E5a I} & {56} & {GPS L1CI} & {GPS L1C D} \\
    {27} & {GAL E5Q} & {GAL E5a Q} & {57} & {GPS L1CQ} & {GPS L1C P} \\
    {28} & {GAL E5X} & {GAL E5a I+Q} & {58} & {GPS L1CX} & {GPS L1C D+P} \\ 
    {29} & {GLO L1P} & {GLONASS L1SF} \\
    \bottomrule
  \end{longtable}
\captionof{table}{GNSS Signals Table}
\end{center}

((* block messages_table *))
((* endblock *))

((* block messages_desc *))
((* endblock *))

\end{document}
